package com.cn.wanxi.autoconfig.controller;

import com.cn.learn.starter.service.ITimeService;
import com.cn.wanxi.autoconfig.vo.ResultVO;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @ClassName ThreadController
 * @Description 线程接口层
 * @Author JiJiang
 * @Date 2023/7/6 22:09
 * @Version 1.0
 */
@RestController
@RequestMapping("/thread")
public class ThreadController {


    @Resource
    private ITimeService timeService;


    /**
     * 使用futureTask计算1亿的阶乘
     *
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @GetMapping("/compute/factorial/futureTask")
    public ResultVO<Object> useFutureCompute() throws ExecutionException, InterruptedException {


        long start = System.currentTimeMillis();


        int toCalculateNum = 1000000000;


        int groupCount = 2;


        int half = toCalculateNum / groupCount;

        // Callable 函数式编程接口，用于计算，无入参只需指定计算结果的返回类型
        FutureTask<Long> futureTask1 = new FutureTask<>(new Callable<Long>() {
            @Override
            public Long call() throws Exception {

                long retNum = computeFactorial(1, half);
                System.out.println("=========================");
                System.out.println("futureTask1 计算完成：" + timeService.getTimeForYMDHIS(System.currentTimeMillis()));
                System.out.println("=========================");

                return retNum;
            }
        });


        FutureTask<Long> futureTask2 = new FutureTask<Long>(new Callable<Long>() {
            @Override
            public Long call() throws Exception {
                long retNum = computeFactorial(half + 1, toCalculateNum);

                System.out.println("=========================");
                System.out.println("futureTask2 计算完成：" + timeService.getTimeForYMDHIS(System.currentTimeMillis()));
                System.out.println("=========================");

                return retNum;

            }
        });

        new Thread(futureTask1).start();
        new Thread(futureTask2).start();
        long result1 = futureTask1.get();
        long result2 = futureTask2.get();

        long data = result1 + result2;
        System.out.println("=========================");
        System.out.println("总数计算完毕!时间为：" + timeService.getTimeForYMDHIS(System.currentTimeMillis()));
        System.out.println("=========================");

        long end = System.currentTimeMillis();

        Map<String, Object> retData = new HashMap<>();


        retData.put("useTime", (end - start) + " ms");
        retData.put("result", toCalculateNum + " sum is " + data);

        return ResultVO.getResult("使用futureTask计算成功", retData);
    }

    /**
     * 使用常规方法计算1亿的阶乘
     *
     * @return
     */
    @GetMapping("/compute/factorial/normal")
    public ResultVO<Object> normalCompute() {
        long start = System.currentTimeMillis();
        int toCalculateNum = 1000000000;
        long data = computeFactorial(1, toCalculateNum);
        long end = System.currentTimeMillis();
        Map<String, Object> retData = new HashMap<>();
        retData.put("useTime", (end - start) + " ms");
        retData.put("result", toCalculateNum + " sum is " + data);
        return ResultVO.getResult("不使用futureTask计算成功", retData);
    }


    //region 私有方法

    /**
     * 计算阶乘
     *
     * @param startNum
     * @param endNum
     * @return
     */
    private static long computeFactorial(int startNum, int endNum) {


        long retData = 0L;
        for (int i = startNum; i <= endNum; i++) {
            retData += i;
        }
        return retData;

    }

    //endregion

}
